`timescale 1ns/1ps
`default_nettype none
// ============================================================================
// 文件名：rtl/csrfile.v —— RV32I 最小 M 模式 CSR 档案
//  支持：mstatus(0x300), mtvec(0x305), mscratch(0x340), mepc(0x341), mcause(0x342)
//  指令：CSRRW/CSRRS/CSRRC 及 *I 变体；ECALL；MRET
//  时序：在 EX 阶段组合读出 old 值，时钟上升沿写入新值；同时给出 trap_taken/target
// ============================================================================
module csrfile(
    input  wire        clk,
    input  wire        rstn,          // 同步低有效复位

    // 来自控制/EX 的 CSR 操作
    input  wire        csr_en,        // 本拍是否为 CSR 指令
    input  wire [2:0]  csr_funct3,    // 001/010/011/101/110/111
    input  wire [11:0] csr_addr,      // instr[31:20]
    input  wire [31:0] rs1_val,       // CSR 指令源（*I 以 zimm 替代）
    input  wire [4:0]  zimm,          // CSR*I 的 5bit 立即数

    // Trap/MRET
    input  wire        ecall,         // ECALL
    input  wire        mret,          // MRET
    input  wire        exc_valid,     // ★ 新增：本拍有同步异常（例如地址不对齐）
    input  wire [31:0] exc_cause,     // ★ 新增：异常原因码（4=load-misal, 6=store-misal）
    input  wire [31:0] exc_tval,
    
    output reg         trap_taken,    // 触发控制流重定向
    output reg  [31:0] trap_target,   // 重定向目标（ECALL->mtvec，MRET->mepc）
    input  wire [31:0] cur_pc,        // EX 阶段当前指令 PC（写 mepc 用）

    // 提供给 WB 的旧值（CSRR* 的“旧 CSR”回写）
    output reg  [31:0] csr_rdata
);

    // -------------------------
    // CSR 地址常量
    // -------------------------
    localparam CSR_MSTATUS  = 12'h300;
    localparam CSR_MTVEC    = 12'h305;
    localparam CSR_MSCRATCH = 12'h340;
    localparam CSR_MEPC     = 12'h341;
    localparam CSR_MCAUSE   = 12'h342;
    localparam CSR_MTVAL    = 12'h343;

    // -------------------------
    // CSR 寄存器
    // -------------------------
    reg [31:0] mstatus;   // 仅占位实现：保留/简单位
    reg [31:0] mtvec;
    reg [31:0] mscratch;
    reg [31:0] mepc;
    reg [31:0] mcause;
    reg [31:0] mtval; 

    // 复位：清零（mtvec/mepc/mcause/mscratch），mstatus 置 0
    always @(posedge clk) begin
        if (!rstn) begin
            mstatus  <= 32'h00000000;
            mtvec    <= 32'h00000000;
            mscratch <= 32'h00000000;
            mepc     <= 32'h00000000;
            mcause   <= 32'h00000000;
            mtval    <= 32'h00000000;
        end else begin
            // -------------------------
            // ECALL / MRET 处理（优先级通常高于 CSR 写）
            // -------------------------
            if (exc_valid) begin
                mepc   <= cur_pc;
                mcause <= exc_cause;
                mtval  <= exc_tval; 
            end else if (ecall) begin
                // M 环境调用：mcause=11（同步异常，来自 M-mode）
                // mepc 记录“陷入指令”PC（这里取 EX 的 cur_pc）
                mepc   <= cur_pc;
                mcause <= 32'd11;
                mtval  <= 32'h0;
                // mstatus 位简化：不做完整特权状态机处理（可按需扩展）
                // mstatus.MPIE <= mstatus.MIE; mstatus.MIE <= 0; 等
            end else if (mret) begin
                // MRET：通常恢复 mstatus 状态，简化实现略
            end

            // -------------------------
            // CSR 写逻辑
            // -------------------------
            if (csr_en) begin
                // 旧值（用于读改写；组合块也会读，这里再取一次不影响）
                // 注意：*I 变体使用 zimm（5bit）零扩展
                // CSRRW/CSRRS/CSRRC：使用 rs1_val
                // CSRRWI/CSRRSI/CSRRCI：使用 zimm_val
                // 写入规则：
                //  - CSRRW(I)  ：直接写 new = src
                //  - CSRRS(I)  ：new = old | src   （src==0 时，不修改）
                //  - CSRRC(I)  ：new = old & ~src  （src==0 时，不修改）
                // 规范：rd==x0 时 CSRRW 仍应写；CSRRS/CSRRC 在 src==0 时不写。
                // 这里严格按规则实现。
                reg [31:0] old_val;
                reg [31:0] src_val;
                reg        do_write;
                reg [31:0] new_val;

                // 取旧值
                case (csr_addr)
                    CSR_MSTATUS : old_val = mstatus;
                    CSR_MTVEC   : old_val = mtvec;
                    CSR_MSCRATCH: old_val = mscratch;
                    CSR_MEPC    : old_val = mepc;
                    CSR_MCAUSE  : old_val = mcause;
                    CSR_MTVAL    : old_val = mtval;
                    default     : old_val = 32'h00000000; // 未实现的 CSR 读出 0
                endcase

                // 选择源
                if (csr_funct3[2]) begin
                    // *I 变体（101/110/111）
                    src_val = {27'b0, zimm};
                end else begin
                    // 非 I 变体（001/010/011）
                    src_val = rs1_val;
                end

                // 计算是否写入以及新值
                do_write = 1'b0;
                new_val  = old_val;
                case (csr_funct3)
                    3'b001, // CSRRW
                    3'b101: // CSRRWI
                    begin
                        do_write = 1'b1;
                        new_val  = src_val;
                    end

                    3'b010: // CSRRS
                    begin
                        do_write = (src_val != 32'b0); // src==0 时不写
                        new_val  = old_val | src_val;
                    end
                    3'b110: // CSRRSI
                    begin
                        do_write = (src_val != 32'b0);
                        new_val  = old_val | src_val;
                    end

                    3'b011: // CSRRC
                    begin
                        do_write = (src_val != 32'b0);
                        new_val  = old_val & ~src_val;
                    end
                    3'b111: // CSRRCI
                    begin
                        do_write = (src_val != 32'b0);
                        new_val  = old_val & ~src_val;
                    end

                    default: begin
                        do_write = 1'b0;
                        new_val  = old_val;
                    end
                endcase

                // 写入目标 CSR
                if (do_write) begin
                    case (csr_addr)
                        CSR_MSTATUS : mstatus  <= new_val;
                        CSR_MTVEC   : mtvec    <= new_val;
                        CSR_MSCRATCH: mscratch <= new_val;   // ★ 你的用例关键
                        CSR_MEPC    : mepc     <= new_val;
                        CSR_MCAUSE  : mcause   <= new_val;
                        CSR_MTVAL   : mtval    <= new_val;
                        default     : ; // 未实现 CSR 丢弃写
                    endcase
                end
            end
        end
    end

    // -------------------------
    // 组合：读出旧值用于回写（WB 阶段）
    // -------------------------
    always @* begin
        case (csr_addr)
            CSR_MSTATUS : csr_rdata = mstatus;
            CSR_MTVEC   : csr_rdata = mtvec;
            CSR_MSCRATCH: csr_rdata = mscratch;
            CSR_MEPC    : csr_rdata = mepc;
            CSR_MCAUSE  : csr_rdata = mcause;
            CSR_MTVAL   : csr_rdata = mtval; 
            default     : csr_rdata = 32'h00000000;
        endcase
    end

    // -------------------------
    // 组合：Trap 产生
    // -------------------------
    always @* begin
        // 默认为不跳
        trap_taken  = 1'b0;
        trap_target = 32'h00000000;

        if (exc_valid) begin
            trap_taken  = 1'b1;
            trap_target = mtvec;
        end else if (ecall) begin
            trap_taken  = 1'b1;
            trap_target = mtvec;     // 进入陷阱向量
        end else if (mret) begin
            trap_taken  = 1'b1;
            trap_target = mepc;      // 返回 mepc
        end
    end

endmodule

`default_nettype wire
